package utils;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.google.common.collect.Maps;

import model.GenericScenarie;
import model.PercentageSplitDataSets;
import enumerations.AttributesEnum;

public class InstancesUtils {

	/**
	 * Split an original list of instances into two different lists. The first one will be use for training, and the other for testing.
	 * 
	 * @param total
	 * @param percentage
	 * @return
	 */
	public static PercentageSplitDataSets splitDataSetByPercentage(Map<AttributesEnum, List<GenericScenarie>> sublistsInstancesMap, int total, int percentage) {

		Map<AttributesEnum, List<GenericScenarie>> cloneMap = Maps.newHashMap();
		for (Entry<AttributesEnum, List<GenericScenarie>> entry : sublistsInstancesMap.entrySet()) {
			List<GenericScenarie> scenaries = new ArrayList<GenericScenarie>();
			scenaries.addAll(entry.getValue());
			cloneMap.put(entry.getKey(), scenaries);
		}

		List<GenericScenarie> trainList = new ArrayList<GenericScenarie>();
		List<GenericScenarie> testList = new ArrayList<GenericScenarie>();

		NumberFormat numberDownFormat = DecimalFormat.getInstance();
		numberDownFormat.setMaximumFractionDigits(1);
		numberDownFormat.setRoundingMode(RoundingMode.DOWN);

		NumberFormat numberUpFormat = DecimalFormat.getInstance();
		numberUpFormat.setMaximumFractionDigits(1);
		numberUpFormat.setRoundingMode(RoundingMode.UP);

		int testDataSize = total * percentage / 100;
		// 1- Calculate the quantity of elements to keep from every attribute.
		// 2- Shuffle the list to select randomize elements.
		// 3- Add those elements to the final testSet.
		for (Entry<AttributesEnum, List<GenericScenarie>> entry : cloneMap.entrySet()) {

			long quantity = Math.round((((double) (testDataSize * ((double) entry.getValue().size() / (double) total))) + 0.5));
			Collections.shuffle(entry.getValue());
			for (int i = 0; i < quantity; i++) {
				if (testList.size() < testDataSize) {
					testList.add(entry.getValue().get(0));
					entry.getValue().remove(0);
				}
			}
		}
		// New train list with the rest of the generic scenaries.
		for (List<GenericScenarie> scenaries : cloneMap.values())
			trainList.addAll(scenaries);

		return new PercentageSplitDataSets(trainList, testList);
	}
}
